Aggregating trajectories¶
The aggregation approach implemented in TrajectoryCollectionAggregator is based on Andrienko, N., & Andrienko, G. (2011). Spatial generalization and aggregation of massive movement data. IEEE Transactions on visualization and computer graphics, 17(2), 205-219. and consists of the following main steps:
- Extracting characteristic points from the trajectories
- Grouping the extracted points by spatial proximity
- Computing group centroids and corresponding Voronoi cells
- Dividing trajectories into segments according to the Voronoi cells
- Counting transitions from one cell to another
In [ ]:
import pandas as pd
import geopandas as gpd
import movingpandas as mpd
import shapely as shp
import hvplot.pandas
import matplotlib.pyplot as plt
import folium
from geopandas import GeoDataFrame, read_file
from shapely.geometry import Point, LineString, Polygon
from datetime import datetime, timedelta
from holoviews import opts, dim
import warnings
warnings.filterwarnings("ignore")
plot_defaults = {"linewidth": 5, "capstyle": "round", "figsize": (9, 3), "legend": True}
opts.defaults(
opts.Overlay(active_tools=["wheel_zoom"], frame_width=500, frame_height=400)
)
mpd.show_versions()
MovingPandas 0.19.0 SYSTEM INFO ----------- python : 3.10.14 | packaged by conda-forge | (main, Mar 20 2024, 12:40:08) [MSC v.1938 64 bit (AMD64)] executable : c:\Users\Agarkovam\AppData\Local\miniforge3\envs\mpd-ex\python.exe machine : Windows-10-10.0.19045-SP0 GEOS, GDAL, PROJ INFO --------------------- GEOS : None GEOS lib : None GDAL : 3.8.5 GDAL data dir: None PROJ : 9.4.0 PROJ data dir: C:\Users\Agarkovam\AppData\Local\miniforge3\envs\mpd-ex\Library\share\proj PYTHON DEPENDENCIES ------------------- geopandas : 1.0.1 pandas : 2.2.2 fiona : 1.9.6 numpy : 1.26.4 shapely : 2.0.4 pyproj : 3.6.1 matplotlib : 3.8.4 mapclassify: 2.6.1 geopy : 2.4.1 holoviews : 1.17.1 hvplot : 0.8.3 geoviews : 1.9.6 stonesoup : 1.2
In [ ]:
gdf = read_file("../data/geolife_small.gpkg")
tc = mpd.TrajectoryCollection(gdf, "trajectory_id", t="t")
In [ ]:
tc.hvplot(line_width=7.0, tiles="StamenTonerBackground")
Out[ ]:
In [ ]:
tc.explore(column="trajectory_id", cmap="plasma", style_kwds={"weight": 4})
Out[ ]:
Make this Notebook Trusted to load map: File -> Trust Notebook
TrajectoryCollectionAggregator¶
Generalizing the trip trajectories significantly speeds up the following aggregation step.
In [ ]:
generalized = mpd.MinDistanceGeneralizer(tc).generalize(tolerance=100)
In [ ]:
aggregator = mpd.TrajectoryCollectionAggregator(
generalized,
max_distance=1000,
min_distance=100,
min_stop_duration=timedelta(minutes=5),
)
In [ ]:
pts = aggregator.get_significant_points_gdf()
clusters = aggregator.get_clusters_gdf()
(
pts.hvplot(geo=True, tiles="StamenTonerBackground")
* clusters.hvplot(geo=True, color="red")
)
Out[ ]:
In [ ]:
m = pts.explore(marker_kwds={"radius": 3}, name="Significant points")
clusters.explore(m=m, color="red", marker_kwds={"radius": 3}, name="Cluster centroids")
folium.TileLayer("CartoDB positron").add_to(m)
folium.LayerControl().add_to(m)
m
Out[ ]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [ ]:
flows = aggregator.get_flows_gdf()
In [ ]:
(
flows.hvplot(
geo=True,
hover_cols=["weight"],
line_width=dim("weight") * 7,
color="#1f77b3",
tiles="StamenTonerBackground",
)
* clusters.hvplot(geo=True, color="red", size=dim("n"))
)
Out[ ]:
In [ ]:
m = flows.explore(
style_kwds={"weight": 5},
name="Flows",
)
clusters.explore(
m=m,
color="red",
style_kwds={"style_function": lambda x: {"radius": x["properties"]["n"]}},
name="Clusters",
)
folium.TileLayer("OpenStreetMap").add_to(m)
folium.LayerControl().add_to(m)
m
Out[ ]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [ ]: